#include <atomic>
#include <fstream>
#include "mpp/stream_puller_usb.h"
#include "mpp/stream_pusher.h"
#include "base_util/math_compute.h"
#include "common/mediakit_tool.h"
#include "osd_text.h"

using namespace stream;




int main(int argc, char** argv) {
  int ret = 0;
  std::string streamAddress = argv[1];
  // std::string streamAddress = "/dev/video20";

  LogInfo* log_ifo = new LogInfo(1, "./log", "log"); 

  StreamPullerInfo puller_ifo;
  puller_ifo.oriWidth = 1920;
  puller_ifo.oriHeight = 1080;
  puller_ifo.streamAddress = streamAddress;
  puller_ifo.transferType = "tcp";
  puller_ifo.enType = AV_CODEC_ID_MJPEG;  //h264  MPP_VIDEO_CodingAVC
  puller_ifo.vdecChn = 0;
  std::cout<<"puller_ifo.enType:"<<puller_ifo.enType<<std::endl;
  stream::RKStreamPullerUSB *puller = new stream::RKStreamPullerUSB(&puller_ifo, log_ifo);
  if (ret != (puller->init_params()) != 0) {
    spdlog::get("logger")->info("ERROR puller->init_params error ret:{}\n", ret);
    return ret;
  }
  std::thread(&stream::RKStreamPullerUSB::start_pull, puller).detach();

  common::MediaKitInfo mk_ifo;
  mk_ifo.ok = 0;
  mk_ifo.secret = "XSHJLrQhNWep3s8vzFRth2EQw7CA9tZZ";
  mk_ifo.mediaKitAPI.closeStreams = "/index/api/close_streams";
  mk_ifo.mediaKitAPI.getMediaList = "/index/api/getMediaList";
  mk_ifo.mediaKitClient = "http://127.0.0.1:9080";
  common::api_close_stream(mk_ifo, "live", "stream", log_ifo);

  // stream::CVStreamOsdInfo osd_ifo;
  // osd_ifo.dstWidth = 1920;
  // osd_ifo.dstHeight = 1080;
  // osd_ifo.boxThick = 3;
  // osd_ifo.boxColorNG = cv::Scalar(0, 0, 255);
  // osd_ifo.boxColorOK = cv::Scalar(0, 255, 0);
  // osd_ifo.fontHeight = 30;                        
  // stream::CVOsdText* osder = new stream::CVOsdText(&osd_ifo, log_ifo);
  // if (ret != (osder->init_params()) != 0) {
  //   spdlog::get("logger")->info("ERROR pusher->init_params error ret:{}\n", ret);
  //   return ret;
  // }


  StreamPusherInfo pusher_ifo;
  pusher_ifo.formatName = "flv";
  pusher_ifo.codecProfile = "main";
  pusher_ifo.fps = 25;
  pusher_ifo.bitrate = 4096;        // Mbps
  pusher_ifo.enType = AV_CODEC_ID_H264;   //MPP_VIDEO_CodingAVC
  pusher_ifo.vEncChn = 0;
  pusher_ifo.streamAddress = "rtmp://127.0.0.1:9935/live/stream";
  pusher_ifo.dstWidth = puller_ifo.oriWidth;
  pusher_ifo.dstHeight = puller_ifo.oriHeight;

  RKStreamPusher *pusher = new RKStreamPusher(&pusher_ifo, log_ifo);
  if (ret != (pusher->init_params()) != 0) {
    spdlog::get("logger")->info("ERROR pusher->init_params error ret:{}\n", ret);
    return ret;
  }
  std::thread(&RKStreamPusher::start_push, pusher).detach();

  std::atomic_int push_error, restart_flag;
  push_error = 0;
  restart_flag = 1;
  auto check_stream_thred = [&](common::MediaKitInfo mkt_ifo, LogInfo *log_ifo) {
    int ret = 0;
    std::this_thread::sleep_for(std::chrono::milliseconds(5000));

    while (true) {
      if (restart_flag) {
        std::this_thread::sleep_for(std::chrono::milliseconds(5000));
        restart_flag = 0;
      }
      std::this_thread::sleep_for(std::chrono::milliseconds(500));

      int media_cnt = 0;
      ret = common::api_getMediaList(mkt_ifo, media_cnt, "live", "stream", log_ifo);
      if (ret != 0 || media_cnt == 0) {
        push_error = 1;
      }

    }
  };

  std::thread(check_stream_thred, mk_ifo, log_ifo).detach();

  int cnt = 0;
  stream::ImageBlob buffer(stream::ImageBlobMode_BGR);
  int64_t consume_time = 0;
  int64_t start_time = 0, end_time = 0;
  int error_cnt = 1;
  while(true) {
    std::this_thread::sleep_for(std::chrono::milliseconds(2));
    
    ret = puller->get_frame(buffer);
    if (ret != 0) { 
      error_cnt++;
      if (error_cnt % 500 == 0) {
        std::cout << "error_cnt: " << error_cnt << std::endl;
      }
      continue; 
    }
    error_cnt = 1;

    // 重新推流
    if (push_error == 1) {
      pusher->stop_push();
      delete pusher;
      
      common::api_close_stream(mk_ifo, "live", "stream", log_ifo);

      pusher = new RKStreamPusher(&pusher_ifo, log_ifo);
      if (ret != (pusher->init_params()) != 0) {
        spdlog::get("logger")->info("ERROR pusher->init_params error ret:{}\n", ret);
        return ret;
      }
      std::thread(&RKStreamPusher::start_push, pusher).detach();
      restart_flag = 1;

      continue;
    }

    ret = pusher->add_frame(buffer); 
  }

  // int x = 100;
  // int y = 100;
  // int cnt = 0;
  // stream::ImageBlob buffer(stream::ImageBlobMode_BGR);
  // int64_t consume_time = 0;
  // int64_t start_time = 0, end_time = 0;
  // while(true) {
  //   std::this_thread::sleep_for(std::chrono::milliseconds(2));
  //   if ((x + 1200) >= osd_ifo.dstWidth) {x = 100;}
  //   if (y >= osd_ifo.dstHeight) {y = 100;}
    
  //   ret = puller->get_frame(buffer);
  //   if (ret != 0) { continue; }

  //   // std::cout << "bgr_img w:" << buffer.img.cols << " h:" << buffer.img.rows << " c:" << buffer.img.channels() << std::endl;
  //   start_time = duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();
  //   std::vector<stream::OSDDrawInfo> osdd_ifos;
  //   for(int i = 0; i < 9; i++) {
  //     stream::OSDDrawInfo osdd_ifo;
  //     // osdd_ifo.texts.push_back("O正确");
  //     osdd_ifo.texts.push_back("N错误");
  //     osdd_ifo.x = x + i*150;
  //     osdd_ifo.y = y;
  //     osdd_ifo.w = 100;
  //     osdd_ifo.h = 200;
  //     osdd_ifos.push_back(osdd_ifo);
  //   }
  //   x++;
  //   y++;
  //   ret = osder->draw_osd(buffer, osdd_ifos);
  //   end_time = duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();
  //   consume_time += end_time - start_time;
  //   if (++cnt % 100 == 0) {
  //     std::cout << "draw_osd: " << consume_time * 1.0 / cnt << std::endl;
  //     consume_time = 0;
  //     cnt = 0;
  //   }


  //   ret = pusher->add_frame(buffer); 

  // }

  return 0;
}
